/******************************************************************************* * Copyright (c) 2000, 2012 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.swt.internal.theme; import org.eclipse.swt.*; import org.eclipse.swt.graphics.*; import org.eclipse.swt.internal.*; import org.eclipse.swt.internal.cairo.Cairo; import org.eclipse.swt.internal.gtk.*; public class ButtonDrawData extends DrawData { public ButtonDrawData() { state = new int[1]; } @Override void draw(Theme theme, GC gc, Rectangle bounds) { int state = this.state[DrawData.WIDGET_WHOLE]; long /*int*/ drawable = gc.getGCData().drawable; if ((style & SWT.RADIO) != 0) { long /*int*/ radioButtonHandle = theme.radioButtonHandle; long /*int*/ gtkStyle = OS.gtk_widget_get_style (radioButtonHandle); theme.transferClipping (gc, gtkStyle); int indicator_size = theme.getWidgetProperty(radioButtonHandle, "indicator-size"); int indicator_spacing = theme.getWidgetProperty(radioButtonHandle, "indicator-spacing"); int interior_focus = theme.getWidgetProperty(radioButtonHandle, "interior-focus"); int focus_line_width = theme.getWidgetProperty(radioButtonHandle, "focus-line-width"); int focus_padding = theme.getWidgetProperty(radioButtonHandle, "focus-padding"); int border_width = OS.gtk_container_get_border_width(radioButtonHandle); int x = bounds.x + indicator_spacing + border_width; int y = bounds.y + (bounds.height - indicator_size) / 2; if (interior_focus == 0) { x += focus_line_width + focus_padding; } int shadow_type; if ((state & DrawData.GRAYED) != 0) { shadow_type = OS.GTK_SHADOW_ETCHED_IN; } else if ((state & DrawData.SELECTED) != 0) { shadow_type = OS.GTK_SHADOW_IN; } else { shadow_type = OS.GTK_SHADOW_OUT; } byte[] detail = Converter.wcsToMbcs(null, "radiobutton", true); if ((state & DrawData.HOT) != 0) { int prelight_x, prelight_y, prelight_width, prelight_height; prelight_x = bounds.x + border_width; prelight_y = bounds.y + border_width; prelight_width = bounds.width - (2 * border_width); prelight_height = bounds.height - (2 * border_width); gtk_render_frame (gtkStyle, drawable, OS.GTK_STATE_PRELIGHT, OS.GTK_SHADOW_ETCHED_OUT, null, radioButtonHandle, detail, prelight_x, prelight_y, prelight_width, prelight_height); } int state_type = getStateType(DrawData.WIDGET_WHOLE); OS.gtk_paint_option(gtkStyle, drawable, state_type, shadow_type, null, radioButtonHandle, detail, x, y, indicator_size, indicator_size); if (clientArea != null) { clientArea.x = bounds.x + 2 * indicator_spacing + border_width + indicator_size; clientArea.y = bounds.y + border_width; clientArea.width = bounds.width - (2 * indicator_spacing + 2 * border_width + indicator_size); clientArea.height = bounds.height - 2 * border_width; } return; } if ((style & SWT.CHECK) != 0) { long /*int*/ checkButtonHandle = theme.checkButtonHandle; long /*int*/ gtkStyle = OS.gtk_widget_get_style (checkButtonHandle); theme.transferClipping (gc, gtkStyle); int indicator_size = theme.getWidgetProperty(checkButtonHandle, "indicator-size"); int indicator_spacing = theme.getWidgetProperty(checkButtonHandle, "indicator-spacing"); int interior_focus = theme.getWidgetProperty(checkButtonHandle, "interior-focus"); int focus_line_width = theme.getWidgetProperty(checkButtonHandle, "focus-line-width"); int focus_padding = theme.getWidgetProperty(checkButtonHandle, "focus-padding"); int border_width = OS.gtk_container_get_border_width(checkButtonHandle); int x = bounds.x + indicator_spacing + border_width; int y = bounds.y + (bounds.height - indicator_size) / 2; if (interior_focus == 0) { x += focus_line_width + focus_padding; } int shadow_type; if ((state & DrawData.GRAYED) != 0) { shadow_type = OS.GTK_SHADOW_ETCHED_IN; } else if ((state & DrawData.SELECTED) != 0) { shadow_type = OS.GTK_SHADOW_IN; } else { shadow_type = OS.GTK_SHADOW_OUT; } byte[] detail = Converter.wcsToMbcs(null, "checkbutton", true); if ((state & DrawData.HOT) != 0) { int prelight_x, prelight_y, prelight_width, prelight_height; prelight_x = bounds.x + border_width; prelight_y = bounds.y + border_width; prelight_width = bounds.width - (2 * border_width); prelight_height = bounds.height - (2 * border_width); gtk_render_frame (gtkStyle, drawable, OS.GTK_STATE_PRELIGHT, OS.GTK_SHADOW_ETCHED_OUT, null, checkButtonHandle, detail, prelight_x, prelight_y, prelight_width, prelight_height); } int state_type = getStateType(DrawData.WIDGET_WHOLE); gtk_render_check (gtkStyle, drawable, state_type, shadow_type, checkButtonHandle, detail, x, y, indicator_size, indicator_size); if (clientArea != null) { clientArea.x = bounds.x + 2 * indicator_spacing + border_width + indicator_size; clientArea.y = bounds.y + border_width; clientArea.width = bounds.width - (2 * indicator_spacing + 2 * border_width + indicator_size); clientArea.height = bounds.height - 2 * border_width; } return; } if ((style & SWT.PUSH) != 0) { long /*int*/ buttonHandle = theme.buttonHandle; long /*int*/ gtkStyle = OS.gtk_widget_get_style (buttonHandle); theme.transferClipping (gc, gtkStyle); int focus_line_width = theme.getWidgetProperty(buttonHandle, "focus-line-width"); int focus_padding = theme.getWidgetProperty(buttonHandle, "focus-padding"); int border_width = OS.gtk_container_get_border_width(buttonHandle); GtkBorder default_border = new GtkBorder(); long /*int*/ default_border_ptr = theme.getBorderProperty(buttonHandle, "default-border"); if (default_border_ptr != 0) { OS.memmove(default_border, default_border_ptr, GtkBorder.sizeof); OS.gtk_border_free(default_border_ptr); } else { default_border.left = default_border.right = default_border.top = default_border.bottom = 1; } GtkBorder default_outside_border = new GtkBorder(); long /*int*/ default_outside_border_ptr = theme.getBorderProperty(buttonHandle, "default-outside-border"); if (default_outside_border_ptr != 0) { OS.memmove(default_outside_border, default_outside_border_ptr, GtkBorder.sizeof); OS.gtk_border_free(default_outside_border_ptr); } else { default_outside_border.left = default_outside_border.right = default_outside_border.top = default_outside_border.bottom = 0; } int x = bounds.x + border_width; int y = bounds.y + border_width; int width = bounds.width - border_width * 2; int height = bounds.height - border_width * 2; int relief = OS.gtk_button_get_relief(buttonHandle); byte[] detail = Converter.wcsToMbcs(null, (state & DrawData.DEFAULTED) != 0 ? "buttondefault" : "button", true); if ((state & DrawData.DEFAULTED) != 0 && relief == OS.GTK_RELIEF_NORMAL) { gtk_render_box (gtkStyle, drawable, OS.GTK_STATE_NORMAL, OS.GTK_SHADOW_IN, null, buttonHandle, detail, x, y, width, height); x += default_border.left; y += default_border.top; width -= default_border.left + default_border.right; height -= default_border.top + default_border.bottom; } else if ((state & DrawData.DEFAULTED) != 0) { x += default_outside_border.left; y += default_outside_border.top; width -= default_outside_border.left + default_outside_border.right; height -= default_outside_border.top + default_outside_border.bottom; } int shadow_type = OS.GTK_SHADOW_OUT; if ((state & (DrawData.SELECTED | DrawData.PRESSED)) != 0) shadow_type = OS.GTK_SHADOW_IN; int state_type = getStateType(DrawData.WIDGET_WHOLE); if (relief != OS.GTK_RELIEF_NONE || ((state & (DrawData.PRESSED | DrawData.HOT)) != 0)) { gtk_render_box (gtkStyle, drawable, state_type, shadow_type, null, buttonHandle, detail, x, y, width, height); } if ((state & DrawData.FOCUSED) != 0) { int child_displacement_y = theme.getWidgetProperty(buttonHandle, "child-displacement-y"); int child_displacement_x = theme.getWidgetProperty(buttonHandle, "child-displacement-x"); int displace_focus = theme.getWidgetProperty(buttonHandle, "displace-focus"); int interior_focus = theme.getWidgetProperty(buttonHandle, "interior-focus"); if (interior_focus != 0) { int xthickness = OS.gtk_style_get_xthickness(gtkStyle); int ythickness = OS.gtk_style_get_ythickness(gtkStyle); x += xthickness + focus_padding; y += ythickness + focus_padding; width -= 2 * (xthickness + focus_padding); height -= 2 * (ythickness + focus_padding); } else { x -= focus_line_width + focus_padding; y -= focus_line_width + focus_padding; width += 2 * (focus_line_width + focus_padding); height += 2 * (focus_line_width + focus_padding); } if ((state & DrawData.PRESSED) != 0 && displace_focus != 0) { x += child_displacement_x; y += child_displacement_y; } gtk_render_focus (gtkStyle, drawable, state_type, null, buttonHandle, detail, x, y, width, height); } if (clientArea != null) { clientArea.x = bounds.x + border_width; clientArea.y = bounds.y + border_width; clientArea.width = bounds.width - 2 * border_width; clientArea.height = bounds.height - 2 * border_width; } return; } } @Override int hit(Theme theme, Point position, Rectangle bounds) { return bounds.contains(position) ? DrawData.WIDGET_WHOLE : DrawData.WIDGET_NOWHERE; } void gtk_render_option (long /*int*/ style, long /*int*/ window, int state_type, int shadow_type, GdkRectangle area, long /*int*/ widget, byte[] detail, int x , int y, int width, int height) { if (OS.GTK3) { long /*int*/ cairo = OS.gdk_cairo_create (window); long /*int*/ context = OS.gtk_widget_get_style_context (style); OS.gtk_render_option (context, cairo, x, y, width, height); Cairo.cairo_destroy (cairo); } else { OS.gtk_paint_option (style, window, state_type, shadow_type, area, widget, detail, x, y, width, height); } } void gtk_render_check(long /*int*/ style, long /*int*/ window, int state_type, int shadow_type, long /*int*/ widget, byte[] detail, int x , int y, int width, int height) { if (OS.GTK3) { long /*int*/ cairo = OS.gdk_cairo_create (window); long /*int*/ context = OS.gtk_widget_get_style_context (style); OS.gtk_render_check (context, cairo, x, y, width, height); Cairo.cairo_destroy (cairo); } else { OS.gtk_paint_check (style, window, state_type, shadow_type, null, widget, detail, x, y, width, height); } } }